// Copyright 叶湘 ( weixin:yexiang841, email:yexiang841@qq.com ), Shitouren Studio. All Rights Reserved.

#include "PlayerState/Q3D_CPPA_PlayerState.h"
#include "PawnState/Q3D_CPPU_PawnState.h"
#include "GameFramework/SpectatorPawn.h"
#include "Logger/Q3D_CPPU_Logger.h"

AQ3D_CPPA_PlayerState::AQ3D_CPPA_PlayerState()
{
}

AQ3D_CPPA_PlayerState::~AQ3D_CPPA_PlayerState()
{
}

void AQ3D_CPPA_PlayerState::Q3D_F_PawnState_Inc(UQ3D_CPPU_PawnState *ptr_u_pawn_state, bool &bool_success, FString &string_log)
{
    // 参数检查
    if (!ptr_u_pawn_state)
    {
        bool_success = false;
        string_log = "Invalid_Ptr_U_PawnState";
        Q3D_LOG(Error, string_log);
        return;
    }
    // 加入 TMap
    this->Map_Name_To_Ptr_U_PawnState.Add(ptr_u_pawn_state->Name_Id, ptr_u_pawn_state);
    // 设置引用
    ptr_u_pawn_state->Ptr_A_PlayerState = this;
    // 日志
    int32 int_player_index_tmp;
    ptr_u_pawn_state->Q3D_F_PlayerIndex_Get(int_player_index_tmp);
    Q3D_LOG(Log, "Inc_[" + ptr_u_pawn_state->String_NickName + "]_To_Player_[" + FString::FromInt(int_player_index_tmp) + "]_Total_[" + FString::FromInt(this->Map_Name_To_Ptr_U_PawnState.Num()) + "]");
    // 广播
    Q3D_ED_PawnState_Inc.Broadcast(ptr_u_pawn_state);
    // 返回值
    bool_success = true;
    string_log = FString("");
    return;
}

void AQ3D_CPPA_PlayerState::Q3D_F_PawnState_Dec(UQ3D_CPPU_PawnState *ptr_u_pawn_state, bool &bool_success, FString &string_log, UQ3D_CPPU_PawnState *&ptr_u_pawn_state_next)
{
    // 参数检查
    if (!ptr_u_pawn_state)
    {
        bool_success = false;
        string_log = FString("Invalid_Ptr_U_PawnState");
        ptr_u_pawn_state_next = nullptr;
        Q3D_LOG(Error, string_log);
        return;
    }
    // 取 Value 数组
    TArray<UQ3D_CPPU_PawnState *> array_values;
    this->Map_Name_To_Ptr_U_PawnState.GenerateValueArray(array_values);
    // 如果没找到
    int32 int_index;
    if (!array_values.Find(ptr_u_pawn_state, int_index))
    {
        bool_success = false;
        string_log = "Missed_[" + ptr_u_pawn_state->Name_Id.ToString() + "]";
        ptr_u_pawn_state_next = nullptr;
        Q3D_LOG(Error, string_log);
        return;
    }
    // 如果找到了
    // 先确定下一个 PawnState
    if (this->Map_Name_To_Ptr_U_PawnState.Num() <= 1)
    {
        // 删掉就没有下一个了
        ptr_u_pawn_state_next = nullptr;
    }
    else
    {
        // 越界就循环
        if ((int_index + 1) == this->Map_Name_To_Ptr_U_PawnState.Num())
        {
            ptr_u_pawn_state_next = array_values[0];
        }
        else
        {
            ptr_u_pawn_state_next = array_values[int_index + 1];
        }
    }
    // 从 TMap 中删除
    if (!this->Map_Name_To_Ptr_U_PawnState.Remove(ptr_u_pawn_state->Name_Id))
    {
        // 正常不会出现这里，以防万一(多线程环境)
        bool_success = false;
        string_log = "Pawn_Found_But_Name_Missed_[" + ptr_u_pawn_state->Name_Id.ToString() + "]";
        ptr_u_pawn_state_next = nullptr;
        Q3D_LOG(Error, string_log);
        return;
    }
    // 日志
    int32 int_player_index_tmp;
    ptr_u_pawn_state->Q3D_F_PlayerIndex_Get(int_player_index_tmp);
    Q3D_LOG(Log, "Dec_[" + ptr_u_pawn_state->String_NickName + "]_To_Player_[" + FString::FromInt(int_player_index_tmp) + "]_Total_[" + FString::FromInt(this->Map_Name_To_Ptr_U_PawnState.Num()) + "]");
    // 广播
    Q3D_ED_PawnState_Dec.Broadcast(ptr_u_pawn_state);
    // 返回值
    bool_success = true;
    string_log = FString("");
    return;
}

void AQ3D_CPPA_PlayerState::Q3D_F_PawnState_Find(APawn *ptr_a_pawn, UQ3D_CPPU_PawnState *&ptr_u_pawn_state) const
{
    // 参数检查
    if (!ptr_a_pawn)
    {
        ptr_u_pawn_state = nullptr;
        Q3D_LOG(Error, "Invalid_Ptr_U_PawnState");
        return;
    }
    // 取 Value 数组
    TArray<UQ3D_CPPU_PawnState *> array_values;
    this->Map_Name_To_Ptr_U_PawnState.GenerateValueArray(array_values);
    // 遍历查找
    for (UQ3D_CPPU_PawnState *one : array_values)
    {
        if (ptr_a_pawn == one->Ptr_A_Pawn)
        {
            ptr_u_pawn_state = one;
            // 日志
            int32 int_player_index_tmp;
            ptr_u_pawn_state->Q3D_F_PlayerIndex_Get(int_player_index_tmp);
            Q3D_LOG(Log, "Found_[" + ptr_a_pawn->GetName() + "]_To_Player_[" + FString::FromInt(int_player_index_tmp) + "]");
            return;
        }
    }
    ptr_u_pawn_state = nullptr;
    int32 int_player_index_tmp;
    ptr_u_pawn_state->Q3D_F_PlayerIndex_Get(int_player_index_tmp);
    Q3D_LOG(Warning, "Missed_[" + ptr_a_pawn->GetName() + "]_To_Player_[" + FString::FromInt(int_player_index_tmp) + "]");
    return;
}

void AQ3D_CPPA_PlayerState::Q3D_F_PawnState_Spectator_Set(UQ3D_CPPU_PawnState *ptr_u_pawn_state, bool &bool_success, FString &string_log)
{
    // 参数检查
    if (!ptr_u_pawn_state)
    {
        bool_success = false;
        string_log = FString("Invalid_Ptr_U_PawnState");
        Q3D_LOG(Error, string_log);
        return;
    }
    // SpectatorPawn 类型检查
    if (!Cast<ASpectatorPawn>(ptr_u_pawn_state->Ptr_A_Pawn))
    {
        bool_success = false;
        string_log = FString("Cast_To_Q3D_CPPA_SpectatorPawn_Failed");
        Q3D_LOG(Error, string_log);
        return;
    }
    // 存储
    this->Ptr_U_PawnState_Spectator = ptr_u_pawn_state;
    // 设置引用
    ptr_u_pawn_state->Ptr_A_PlayerState = this;
    // 日志
    int32 int_player_index_tmp;
    ptr_u_pawn_state->Q3D_F_PlayerIndex_Get(int_player_index_tmp);
    Q3D_LOG(Log, "Set_Spectator_[" + ptr_u_pawn_state->String_NickName + "]_To_Player_[" + FString::FromInt(int_player_index_tmp) + "]");
    // 返回值
    bool_success = true;
    string_log = FString("");
    return;
}

void AQ3D_CPPA_PlayerState::Q3D_F_PawnState_Spectator_Unset(bool &bool_success, FString &string_log)
{
    FString string_pawn_nickname_tmp = this->Ptr_U_PawnState_Spectator->String_NickName;
    int32 int_player_index_tmp;
    this->Ptr_U_PawnState_Spectator->Q3D_F_PlayerIndex_Get(int_player_index_tmp);
    // 存储
    this->Ptr_U_PawnState_Spectator = nullptr;
    // 日志
    Q3D_LOG(Log, "Unset_Spectator_[" + string_pawn_nickname_tmp + "]_To_Player_[" + FString::FromInt(int_player_index_tmp) + "]");
    // 返回值
    bool_success = true;
    string_log = FString("");
    return;
}
